/*****************************************************************************/
/*                                                                           */
/*    Domino Operation System Kernel Module                                  */
/*                                                                           */
/*    Copyright (C) 2008 Laszlo Arvai                                        */
/*                                                                           */
/*    ------------------------------------------------------------------     */
/*    25LC256 EEPROM driver module                                           */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Includes
#include "drvEEPROM.h"
#include "drvIOConfig.h"

///////////////////////////////////////////////////////////////////////////////
// Constants

// 25LC256 Serial EEPROM commands
#define SEE_WRSR	1			// write status register
#define SEE_WRITE	2			// write command
#define SEE_READ	3			// read command
#define SEE_WDI		4			// write disable
#define SEE_STAT	5			// read status register
#define SEE_WEN		6			// write enable

///////////////////////////////////////////////////////////////////////////////
// Initialize EEPROM
void drvInitEEPROM( void)
{
	InitEEPROMSPI();
	InitEEPROMCS();
}

///////////////////////////////////////////////////////////////////////////////
// Read status
dosByte drvEEPROMReadStatus( void)
{
	// Check the Serial EEPROM status register
	dosByte status;
	
	EEPROMCS(PIN_LOW);									// select the Serial EEPROM
	EEPROMSendReceiveByte( SEE_STAT );	// send a READ STATUS COMMAND
	status = EEPROMSendReceiveByte(0);	// send/receive
	EEPROMCS(PIN_HIGH);									// deselect terminate command
	
	return status;
}

///////////////////////////////////////////////////////////////////////////////
// Write enable
void drvEEPROMWriteEnable(void)
{
	// send a Write Enable command
	EEPROMCS(PIN_LOW);									// select the Serial EEPROM
	EEPROMSendReceiveByte(SEE_WEN);			// write enable command
	EEPROMCS(PIN_HIGH);									// deselect terminate command
}

///////////////////////////////////////////////////////////////////////////////
// read block from eeprom
void drvEEPROMReadBlock( dosWord in_address, dosByte* out_buffer, dosWord in_length)
{
	dosWord i;
	
	// select eeprom and send read command and address
	EEPROMCS(PIN_LOW);									// select the Serial EEPROM
	EEPROMSendReceiveByte(SEE_READ);		// read command
	
	EEPROMSendReceiveByte( HIGH(in_address) ); // address MSB first
	EEPROMSendReceiveByte( LOW(in_address) ); // address LSB (word aligned)
	
	// read block data
	for( i = 0; i < in_length; i++ )
	{
		out_buffer[i] = EEPROMSendReceiveByte(0); // send dummy, read byte
	}
	
	// relase CS
	EEPROMCS(PIN_HIGH);									// deselect terminate command
}

///////////////////////////////////////////////////////////////////////////////
// write block to eeprom
void drvEEPROMWriteBlock( dosWord in_address, dosByte* in_buffer, dosWord in_length)
{
	dosWord i;
	
	// Set the Write Enable Latch
	drvEEPROMWriteEnable ();
	
	// perform the write sequence
	EEPROMCS(PIN_LOW);												// select the Serial EEPROM
	EEPROMSendReceiveByte(SEE_WRITE);					// write command
	EEPROMSendReceiveByte(HIGH(in_address));	// address MSB first
	EEPROMSendReceiveByte(LOW(in_address));		// address LSB (word aligned)

	// read block data
	for( i = 0; i < in_length; i++ )
	{
		EEPROMSendReceiveByte(in_buffer[i]); // send dummy, read byte
	}

	// relase CS
	EEPROMCS(PIN_HIGH);										// deselect terminate command
	
	while ( drvEEPROMReadStatus() & 0x1);	// check the WIP flag
}
